﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using SharedContent;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Graphics.PackedVector;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
using ScrollingBackgroundSpace;

namespace MiaProject
{
    class LevelManager2D
    {
        public Level2D level;
        public List<Platform2D> platformList;
        public List<Enemy2D> enemyList;
        public List<Barrel2D> barrelList;
        Shot2D shot;
        Portal2D portal;
        public Gui2D gui;

        public List<Texture2D> textureList;
        private List<String> textureListFile;
        
        
        public const int LEVEL_ALIVE = 1;
        public const int LEVEL_FINISH = 2;
        public const int LEVEL_LOADING = 3;
        
        public int nrEnemysKill;
        public int nrCollisionBall;
        

            
        public int levelStatus;
        public String nextLevel;
        public String currentLevel;
        public Boolean levelWin;
        public Boolean levelLose;
        public int levelAnimationStatus;

        private Boolean keyPressDown;
        private Vector2 origin;
        private Vector2 posPlayer;
        private Vector2 dirPlayer;
        private float angle;
        private Texture2D playerTexture;
        private Texture2D inimigo;
        
        private SmokePlumeParticleSystem2D smokePlume;
        
        private const float TimeBetweenSmokePlumePuffs = 0.05f;
        private float timeTillPuff = 0.0f;

        private float timeTillPortal = 2.0f;

        private float timeTillMonster = 0.0f;
        
        
        private ContentManager content;
        private GraphicsDevice graphicsDevice;
        public Boolean fgLoadGame;

        private static LevelManager2D instance;


        private LevelManager2D()
        {
            platformList = new List<Platform2D>();
            enemyList = new List<Enemy2D>();

            textureList = new List<Texture2D>();

            textureListFile = new List<String>();

            levelAnimationStatus = 0;
            

            levelStatus = LEVEL_ALIVE;
            currentLevel = "Level01";
            nextLevel = "Level01";
            
            nrEnemysKill = 0;
            nrCollisionBall = 0;
            

            fgLoadGame = false;
        }
        public static LevelManager2D getInstance()
        {
            if (instance == null)
                instance = new LevelManager2D();
            return instance;
        }

        public void load(GraphicsDevice graphicsDevice,ContentManager content)
        {
            fgLoadGame = true;
            this.content = content;
            this.graphicsDevice = graphicsDevice;
            this.loadGame2D();
            this.loadNextLevel();


        }//end of method
        public void loadGame2D()
        {

            this.gui = new Gui2D();
            gui.load(graphicsDevice, content);

            //Tiro sempre fixo
            shot = new Shot2D();
            shot.SpriteTexture.Load(content, "img/portal_completo2", shot.frames, shot.framesPerSec);
            shot.setAnimMove();

            //Portal
            portal = new Portal2D();
            portal.SpriteTexture.Load(content, "img/portal_completo", portal.frames, portal.framesPerSec);
            portal.pos = new Vector2(400, 150);


            //Player sempre fixo
            playerTexture = content.Load<Texture2D>("img/shooter");
            origin.X = playerTexture.Width / 2;
            origin.Y = playerTexture.Height / 2;

            inimigo = content.Load<Texture2D>("img/inimigo2");
            
            //particula
            smokePlume = new SmokePlumeParticleSystem2D(9);
            smokePlume.dir = new Vector2(1, 1);
            smokePlume.LoadContent(graphicsDevice, this.content);

            
        }
        private void setupLevel()
        {
            this.gui.nrshots = 5;
            this.shot.status = false;
            this.timeTillPortal = 2;
        }
        public void loadNextLevel()
        {
            this.currentLevel = this.nextLevel;
            this.loadLevel(this.nextLevel);
        }
        public void restartLevel()
        {
            this.loadLevel(this.currentLevel);
        }

        private void loadLevel(String levelFile)
        {
            this.setupLevel();

            platformList = new List<Platform2D>();
            enemyList = new List<Enemy2D>();
            barrelList = new List<Barrel2D>();
            
            levelWin = false;
            levelLose = false;
            posPlayer = new Vector2(60, 420);
            levelAnimationStatus = 0;

            System.Console.WriteLine("~~~~~~~~~LEVEL~~~~~~~~~~~~~~~~");

            level = content.Load<Level2D>("level/2D/" + levelFile);
            System.Console.WriteLine(level.name);

            this.nextLevel = level.nextlevel;

            this.loadPlatform();
            this.loadEnemy();
            this.loadBarrel();

            
            keyPressDown = false;
            angle = 0;
            
            levelStatus = LEVEL_ALIVE;

            Sound s = Sound.getInstance();
            s.setGameVolume();

        }
        
        private void loadPlatform()
        {
            foreach (PlatformContent2D plat in level.platforms)
            {
                
                Platform2D platform = new Platform2D();

                platform.pos = plat.position;
                platform.points = plat.points;
                if (plat.pointsmove.Count > 0)
                {
                    platform.pointsMove = plat.pointsmove;
                    if (plat.trigger != null)
                    {
                        platform.hasTrigger = true;
                        platform.trigger = new Trigger();
                        platform.trigger.pos = plat.trigger;
                        platform.trigger.textureOff = this.getTexture(platform.trigger.textureFileOff);
                        platform.trigger.textureOn = this.getTexture(platform.trigger.textureFileOn);
                    }
                }
                //platform.normal = plat.normal;
                platform.normal = new List<Vector2>();
                for (int i = 0, s = platform.points.Count - 1; i < s; i++)
                    platform.normal.Add(this.getNormal(platform.points[i], platform.points[i + 1]));
                platform.texture = this.getTexture(plat.file);

                platformList.Add(platform);
            }
        }//end of mehtod
        //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        private void loadBarrel()
        {
            foreach (BarrelContent2D item in level.barrels)
            {

                Barrel2D barrel = new Barrel2D();

                barrel.pos = item.position;
                barrel.r = item.r;
                barrel.texture = this.getTexture(item.file);

                barrel.exp = new Explosion2D();
                barrel.exp.explosion = new ExplosionParticleSystem2D(1);
                barrel.exp.explosion.LoadContent(graphicsDevice, content);

                barrel.exp.smoke = new ExplosionSmokeParticleSystem2D(2);
                barrel.exp.smoke.LoadContent(graphicsDevice, content);

                barrelList.Add(barrel);
            }
        }//end of mehtod
        //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        private void loadEnemy()
        {
            foreach (EnemyContent2D e in level.enemies)
            {

                Enemy2D enemy = new Enemy2D();

                enemy.pos = e.position;
                enemy.points = e.points;
                
                enemy.SpriteTexture.Load(content, e.file, enemy.frames, enemy.framesPerSec);
                if(e.points.Count>0)
                    enemy.setAnimMoveRight();
                else
                    enemy.setAnimMoveStoped();
                enemy.exp = new Explosion2D();
                enemy.exp.explosion = new ExplosionParticleSystem2D(1);
                enemy.exp.explosion.LoadContent(graphicsDevice, content);
                enemy.exp.explosion.color = Color.Red;
                enemy.exp.explosion.minInitialSpeed = 40;
                enemy.exp.explosion.maxInitialSpeed = 500;

                enemy.exp.explosion.minAcceleration = 0;
                enemy.exp.explosion.maxAcceleration = 0;

                enemy.exp.explosion.minLifetime = .5f;
                enemy.exp.explosion.maxLifetime = 1.0f;

                enemy.exp.explosion.minScale = .03f;
                enemy.exp.explosion.maxScale = 0.5f;
                

                enemy.exp.smoke = new ExplosionSmokeParticleSystem2D(2);
                enemy.exp.smoke.enabled = false;

                enemyList.Add(enemy);
            }
        }//end of mehtod
        //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        public Vector2 getNormal(Vector2 point1, Vector2 point2)
        {
            Vector2 normal = new Vector2();
            normal.X = point2.Y - point1.Y;
            normal.Y = point1.X - point2.X;

            normal.Normalize();

            return normal;
        }
        /**
            Verifica se a textura ja nao foi carregada, caso sim utiliza
            senao carrega e add a lista
        */
        private Texture2D getTexture(String file)
        {
            //verifica se ja nao foi carregado
            int i = 0;
            foreach (String f in textureListFile)
            {
                if (f.Equals(file))
                    return textureList[i];
                i++;
            }

            Texture2D m = content.Load<Texture2D>(file);
            
            textureList.Add(m);
            textureListFile.Add(file);

            return m;
        }//end of method


        public void update(KeyboardState ks, GameTime gameTime)
        {
            if (levelStatus != LEVEL_ALIVE)
                return;

            gui.update(gameTime);
            
            float elapsed = (float)gameTime.ElapsedGameTime.TotalSeconds;
            
            if (levelAnimationStatus > 0)
            {
                smokePlume.Update(gameTime);
                foreach (Barrel2D b in barrelList)
                    b.update(gameTime);
                foreach (Enemy2D e in enemyList)
                    e.update(gameTime);
                foreach (Barrel2D b in barrelList)
                {
                    checkExplosionBarrel(b, elapsed);
                    b.update(gameTime);
                }
            }   
    

            if (levelAnimationStatus == 1)//matou todos
            {
                portal.setAnimOpen();
                levelAnimationStatus = 2;
                return;
            }
            if (levelAnimationStatus == 2)//portal aberto esperar alguns segundos
            {
                timeTillPortal-=elapsed;
                if (timeTillPortal < 0)
                {
                    levelAnimationStatus = 3;
                    dirPlayer = portal.pos - posPlayer;
                    dirPlayer.Normalize();

                    angle = Vector2.Dot(dirPlayer, new Vector2(0, 1));
                    smokePlume.dir = -dirPlayer;
                    
                    Sound s = Sound.getInstance();
                    s.soundBank.PlayCue("rocket");
                }
                portal.SpriteTexture.UpdateFrame(elapsed);
                return;
            }
            if (levelAnimationStatus == 3)//movimentar nave até o portal
            {
                UpdateSmokePlume(elapsed, posPlayer);
                posPlayer.X += dirPlayer.X * 200 * elapsed;
                posPlayer.Y += dirPlayer.Y * 200 * elapsed;
                
                Vector2 v = portal.pos - posPlayer;
                if(v.Length()<2)
                    levelAnimationStatus = 4;
                
                portal.SpriteTexture.UpdateFrame(elapsed);
                return;
            }
            if (levelAnimationStatus == 4)//iniciar animacao do portal abrindo
            {
                portal.setAnimSend();
                levelAnimationStatus = 5;
                portal.SpriteTexture.UpdateFrame(elapsed);
                Sound s = Sound.getInstance();
                s.soundBank.PlayCue("portal");
                
                return;
            }
            if (levelAnimationStatus == 5)//nave envidada pelo portal
            {
                if (portal.isSended())//portal fechado, finaliza o level
                {
                    levelWin = true;
                    levelAnimationStatus = 6;
                }
                portal.SpriteTexture.UpdateFrame(elapsed);
                
                return;
            }



            if (ks.IsKeyDown(Keys.Down) || ks.IsKeyDown(Keys.Right))
                angle += elapsed * 0.3f;
            else if (ks.IsKeyDown(Keys.Up) || ks.IsKeyDown(Keys.Left))
                angle -= elapsed * 0.3f;


            float circle = MathHelper.Pi * 2;
            angle = angle % circle;

            if (ks.IsKeyDown(Keys.R))
            {
                enemyList[0].status = true;
                foreach (Barrel2D b in barrelList)
                    b.status = true;
            }
            if (!this.keyPressDown && ks.IsKeyDown(Keys.S))
            {
                this.keyPressDown = true;
            }
            if (this.keyPressDown && ks.IsKeyUp(Keys.S))
            {
                this.keyPressDown = false;
                this.fire();
            }


            foreach (Platform2D p in platformList)
                p.update(gameTime);

            foreach (Enemy2D e in enemyList)
                e.update(gameTime);

            foreach (Barrel2D b in barrelList)
            {
                checkExplosionBarrel(b, elapsed);
                b.update(gameTime);
            }

            if (shot.status)
            {
                shot.update(gameTime);
                shot.SpriteTexture.UpdateFrame(elapsed);
                UpdateSmokePlume(elapsed, shot.pos);
                smokePlume.Update(gameTime);
            
                if (this.verifyCollisionPlatform())
                {
                    this.shot.pos.X = this.shot.lastPos.X;
                    this.shot.pos.Y = this.shot.lastPos.Y;
                    this.shot.pos.X += this.shot.dir.X * shot.vel * elapsed;
                    this.shot.pos.Y += this.shot.dir.Y * shot.vel * elapsed;
                    nrCollisionBall++;
                }
                this.verifyCollisionEnemy();
                this.verifyCollisionBarrel(elapsed);

                if (nrCollisionBall >= 10)
                    shot.status = false;

            }
            else
                smokePlume.Update(gameTime);
            
            
            
            if (gui.nrshots <= 0 && nrCollisionBall >= 10)
                levelLose = true;

            timeTillMonster -=elapsed;
            if (timeTillMonster < 0)
            {
                Sound s = Sound.getInstance();
                s.soundBank.PlayCue("monster_left");

                timeTillMonster = 10.0f;
            }
        

        }//end of mehtod
        //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        public void draw(GameTime gameTime, SpriteBatch spriteBatch, GraphicsDeviceManager graphics)
        {

            gui.draw(gameTime, spriteBatch, graphics);
            
            foreach (Platform2D p in platformList)
            {
                if (p.fgshow)
                    spriteBatch.Draw(p.texture, p.pos, new Rectangle(0, 0, p.texture.Width, p.texture.Height), Color.White, p.angle, Vector2.Zero, 1.0f, SpriteEffects.None, 0f);
                if (p.hasTrigger)
                {
                    if(!p.trigger.status)
                        spriteBatch.Draw(p.trigger.textureOff, p.trigger.pos, new Rectangle(0, 0, p.trigger.textureOff.Width, p.trigger.textureOff.Height), Color.White, 0.0f, Vector2.Zero, 1.0f, SpriteEffects.None, 0.0f);
                    else
                        spriteBatch.Draw(p.trigger.textureOn, p.trigger.pos, new Rectangle(0, 0, p.trigger.textureOn.Width, p.trigger.textureOn.Height), Color.White, 0.0f, Vector2.Zero, 1.0f, SpriteEffects.None, 0.0f);

                }
            }
            foreach (Barrel2D b in barrelList)
            {
                if (b.status)
                    spriteBatch.Draw(b.texture, b.pos, new Rectangle(0, 0, b.texture.Width, b.texture.Height), Color.White, 0, Vector2.Zero, 1.0f, SpriteEffects.None, 0f);
                b.exp.Draw(gameTime, spriteBatch, graphics);
            }
            if (levelAnimationStatus == 0 && shot.status)
            {
                shot.SpriteTexture.DrawFrame(spriteBatch, shot.pos);
            }
            
            foreach (Enemy2D e in enemyList)
            {
                if (e.status)
                    e.SpriteTexture.DrawFrame(spriteBatch, e.pos);
                    //spriteBatch.Draw(inimigo, e.pos, new Rectangle(0, 0, inimigo.Width, inimigo.Height), Color.White, 0, Vector2.Zero, 1.0f, SpriteEffects.None, 0f);
                e.exp.Draw(gameTime, spriteBatch, graphics);
            }


            smokePlume.Draw(gameTime, spriteBatch, graphics);

            if (levelAnimationStatus != 5 || !portal.isOpenToSend())
                spriteBatch.Draw(playerTexture, posPlayer, new Rectangle(0, 0, playerTexture.Width, playerTexture.Height), Color.White, this.angle, origin, 1.0f, SpriteEffects.None, 0f);

            if (levelAnimationStatus > 0)
            {
                portal.SpriteTexture.DrawFrame(spriteBatch, portal.pos);
            }

        }//end of method
        //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

        public void verifyCollisionBarrel(float elapsed)
        {
            Rectangle barrelRectangle = new Rectangle();
            Rectangle shotRectangle = new Rectangle((int)(shot.pos.X-shot.getWidth()/2),(int)(shot.pos.Y-shot.getHeight()/2),shot.getWidth(),shot.getHeight());
            foreach (Barrel2D b in barrelList)
            {
                if (!b.status || b.explode)
                    continue;
                barrelRectangle.X = (int)(b.pos.X - b.texture.Width / 2);
                barrelRectangle.Y = (int)(b.pos.Y - b.texture.Height / 2);
                barrelRectangle.Width = (int)b.texture.Width;
                barrelRectangle.Height = (int)b.texture.Height;

                if (barrelRectangle.Intersects(shotRectangle))
                {
                    b.timeExplode = 0;//quando explodido pelo tiro nao tem delay
                    b.explode = true;
                }
                
            }
            
        }
        
        public void checkExplosionBarrel(Barrel2D barrel, float elapsed)
        {

            if (!barrel.status || !barrel.explode)
                return;

            if (barrel.timeExplode > 0)
            {
                barrel.timeExplode -= elapsed;
                return;
            }

            explodeBarrel(barrel, elapsed);
            
        }
        public void explodeBarrel(Barrel2D barrel, float elapsed)
        {

            barrel.status = false;
            barrel.createExplosion(barrel.pos);
            killEnemyByExplosion(barrel.pos, barrel.r);
            killBarrelByExplosion(barrel.pos, barrel.r);

            Sound s = Sound.getInstance();
            s.soundBank.PlayCue("explosion");
        }
        public void killBarrelByExplosion(Vector2 pos, int r)
        {
            foreach (Barrel2D b in barrelList)
            {
                if (b.status && !b.explode && Vector2.Distance(b.pos, pos) < r)
                    b.explode=true;

            }
        }
        public void killEnemyByExplosion(Vector2 pos, int r)
        {
            int contEnemyAlive = 0;
            foreach (Enemy2D enemy in enemyList)
            {
                if (!enemy.status)
                    continue;
                if (Vector2.Distance(enemy.pos, pos) < r)
                {
                    enemy.status = false;
                    enemy.createExplosion(enemy.pos);
                }
                else
                    contEnemyAlive++;
            }
            if (contEnemyAlive == 0)
            {
                portal.setAnimCreate();
                levelAnimationStatus = 1;
            }
        }
        

        public void verifyCollisionEnemy()
        {
            Rectangle enemyRectangle = new Rectangle();
            Rectangle shotRectangle = new Rectangle((int)(shot.pos.X - shot.getWidth() / 2), (int)(shot.pos.Y - shot.getHeight() / 2), shot.getWidth(), shot.getHeight());
            int contEnemyAlive = 0;
            foreach (Enemy2D e in enemyList)
            {
                if (!e.status)
                    continue;
                enemyRectangle.X = (int)(e.pos.X - e.getWidth() / 2);
                enemyRectangle.Y = (int)(e.pos.Y - e.getHeight() / 2);
                enemyRectangle.Width = (int)e.getWidth();
                enemyRectangle.Height = (int)e.getHeight();

                if (enemyRectangle.Intersects(shotRectangle))
                {
                    e.status = false;
                    e.createExplosion(e.pos);

                    Sound s = Sound.getInstance();
                    s.soundBank.PlayCue("monster_dead");

                }
                else
                    contEnemyAlive++;
            }
            if (contEnemyAlive == 0)
            {
                portal.setAnimCreate();
                levelAnimationStatus = 1;
            }
        }
        private Boolean verifyCollisionTrigger(Trigger t)
        {
            if (t.status)
                return false;

            Rectangle triggerRectangle = new Rectangle();
            Rectangle shotRectangle = new Rectangle((int)(shot.pos.X - shot.getWidth() / 2), (int)(shot.pos.Y - shot.getHeight() / 2), shot.getWidth(), shot.getHeight());
            triggerRectangle.X = (int)(t.pos.X);
            triggerRectangle.Y = (int)(t.pos.Y);
            triggerRectangle.Width = (int)t.textureOff.Width;
            triggerRectangle.Height = (int)t.textureOff.Height;

            if (triggerRectangle.Intersects(shotRectangle))
            {
                //t.status = !t.status;
                t.status = true;//ligou uma vez nao tem como desligar
                return true;
            }
            return false;
        }
        
        public Boolean verifyCollisionPlatform()
        {
            //if (this.keyPressDown)
              //  return false;

            Vector2 r = Vector2.Zero;
            Vector2 n = Vector2.Zero;
            Vector2 p = Vector2.Zero;
            Vector2 A = shot.lastPos;
            Vector2 B = shot.pos;
            Vector2 C = Vector2.Zero;
            Vector2 D = Vector2.Zero;


            if (shot.pos.X < 0)
            {
                n.X = 1;
                shot.pos.X = 0;
            }
            else if (shot.pos.X > 800)
            {
                n.X = -1;
                shot.pos.X = 800;
            }
            else if (shot.pos.Y < 0)
            {
                n.Y = 1;
                shot.pos.Y = 0;
            }
            else if (shot.pos.Y > 480)
            {
                n.Y = -1;
                shot.pos.Y = 480;
            }


            if (n != Vector2.Zero)
            {
                r = Vector2.Reflect(shot.dir, n);
                this.shot.dir = r;
                this.shot.dir.Normalize();
                //countCollision++;

                Sound s = Sound.getInstance();
                s.soundBank.PlayCue("collision_wall");


                return true;
            }


            foreach (Platform2D wall in platformList)
            {
                if(wall.hasTrigger)
                    this.verifyCollisionTrigger(wall.trigger);
                for (int i = 0, size = wall.points.Count - 1; i < size; i++)
                {
                    C = wall.pos + wall.points[i];
                    D = wall.pos + wall.points[i + 1];

                    p = DoLinesIntersect(A, B, C, D);
                    if (p != Vector2.Zero)
                    {
                        n = wall.normal[i];

                        float angle = Vector2.Dot(n, shot.dir);
                        float angle2 = MathHelper.ToDegrees(angle);
                        if (angle > 0)
                            continue;

                        //System.Console.WriteLine("-----------------------------------");
                        r = Vector2.Reflect(shot.dir, n);
                        this.shot.dir = r;
                        this.shot.dir.Normalize();
                        //smokePlume.dir = -this.dir;
                        //countCollision++;

                        Sound s = Sound.getInstance();
                        s.soundBank.PlayCue("collision_wall");

                        return true;
                    }
                }
            }
            return false;
        }



        public Vector2 DoLinesIntersect(Vector2 p1, Vector2 p2, Vector2 p3, Vector2 p4)
        {
            // Denominator for ua and ub are the same, so store this calculation
            double d = (p4.Y - p3.Y) * (p2.X - p1.X) - (p4.X - p3.X) * (p2.Y - p1.Y);

            //n_a and n_b are calculated as seperate values for readability
            double n_a = (p4.X - p3.X) * (p1.Y - p3.Y) - (p4.Y - p3.Y) * (p1.X - p3.X);

            double n_b = (p2.X - p1.X) * (p1.Y - p3.Y) - (p2.Y - p1.Y) * (p1.X - p3.X);

            // Make sure there is not a division by zero - this also indicates that
            // the lines are parallel.  
            // If n_a and n_b were both equal to zero the lines would be on top of each 
            // other (coincidental).  This check is not done because it is not 
            // necessary for this implementation (the parallel check accounts for this).
            if (d == 0)
                return Vector2.Zero;

            // Calculate the intermediate fractional point that the lines potentially intersect.
            double ua = n_a / d;
            double ub = n_b / d;

            // The fractional point will be between 0 and 1 inclusive if the lines
            // intersect.  If the fractional calculation is larger than 1 or smaller
            // than 0 the lines would need to be longer to intersect.
            if (ua >= 0d && ua <= 1d && ub >= 0d && ub <= 1d)
            {
                Vector2 p = new Vector2();
                p.X = (float)(p1.X + (ua * (p2.X - p1.X)));
                p.Y = (float)(p1.Y + (ua * (p2.Y - p1.Y)));
                return p;
            }
            return Vector2.Zero;
        }

        public void startShot()
        {
            this.shot.pos.X = 60;
            this.shot.pos.Y = 420;

            this.shot.dir.X = 0;
            this.shot.dir.Y = 0;

            smokePlume.dir = this.shot.dir;

        }
        public void fire()
        {

            if (gui.nrshots <= 0)
                return;

            
            this.startShot();

            this.shot.dir.X = (float)Math.Cos(angle) * 32;
            this.shot.dir.Y = (float)Math.Sin(angle) * 32;


            shot.dir.Normalize();
            smokePlume.dir = -this.shot.dir;

            //System.Console.WriteLine("dir = " + dir.ToString());
            nrCollisionBall = 0;

            gui.nrshots--;
            shot.status = true;

            Sound s = Sound.getInstance();
            s.soundBank.PlayCue("player_shot");

            

        }
        private void UpdateSmokePlume(float dt, Vector2 where)
        {
            timeTillPuff -= dt;


            if (timeTillPuff < 0)
            {
                smokePlume.AddParticles(where);

                // and then reset the timer.
                timeTillPuff = TimeBetweenSmokePlumePuffs;
            }
        }
        
    }//end of class
}//end of namespace
